#ifndef __CONNECTION_POOL__
#define __CONNECTION_POOL__

#include "ursax.h"
// #include <st.h>
#include "anysocket.h"
#include "utcache.h"
#include "networking.h"

extern struct foo_cache* cpool;

int connection_pool_init(size_t capacity);

int connection_pool_fini();

static inline uint64_t cpool_make_key(uint32_t ip, uint16_t port)
{
	return ((uint64_t)port << 32) | ip;
}

static inline st_netfd_t get_connection(uint32_t ip, uint16_t port)
{
	LOG_DEBUG("%s ip %s port %d", __func__, str_ip(ip), port);
	uint64_t connection = 0;
	uint64_t key = cpool_make_key(ip, port);
	int ret = foo_cache_get(cpool, key, &connection);
	return likely(ret == 0) ? (st_netfd_t)connection : make_connection(ip, port);
}

static inline void put_connection(uint32_t ip, uint16_t port, st_netfd_t connection)
{	// st_netfd_t may be an int fd when using anysocket.h
	uint64_t key = cpool_make_key(ip, port);
	int ret = foo_cache_put(cpool, key, (void*)(uint64_t)connection);
	if (ret != 0)
	{
		LOG_DEBUG("put_connection: foo_cache_put failed (due to duplication?)");
		st_netfd_close(connection);
	}
}

static inline void trash_connection(uint32_t ip, uint16_t port, st_netfd_t connection)
{
	LOG_DEBUG("%s ip %s port %d", __func__, str_ip(ip), port);
	(void)ip; (void)port;
	st_netfd_close(connection);
}

static inline uint32_t
get_connection_number(void)
{
	if (NULL != cpool) {
		return (uint32_t)foo_cache_entry_count(cpool);
	} else {
		return 0;
	}
}

#define conn_record st_netfd_t
#define the_connection(x) x
#include "pooled-functions.h"
#undef the_connection
#undef conn_record

#endif
